package main.leetcode.offer.firstround.from03to50;

import java.util.LinkedList;
import java.util.Queue;

/**
 * 13.机器人的运动范围
 *
 * <p>地上有一个m行n列的方格，从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0]
 * 的格子开始移动，它每次可以向左、右、上、下移动一格（不能移动到方格外），也不能进入行坐标和列坐标的数位之和大于k的格子。例如，当k为18时，机器人能够进入方格 [35, 37]
 * ，因为3+5+3+7=18。但它不能进入方格 [35, 38]，因为3+5+3+8=19。请问该机器人能够到达多少个格子？
 *
 * <p>示例 1：输入：m = 2, n = 3, k = 1 输出：3
 *
 * <p>示例 2：输入：m = 3, n = 1, k = 0 输出：1
 *
 * <p>提示：1 <= n,m <= 100 0 <= k <= 20
 *
 * <p>来源：力扣（LeetCode） 链接：https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 *
 * <p>注意：他要的是所有可以走到的合法的格子，不是一次最远走多少格子
 */
public class ex13 {
    private int num;
    private boolean[][] isVisited;

    public static void main(String[] args) {
        System.out.println(new ex13().movingCount1(16, 8, 4));
        System.out.println(new ex13().movingCount1(1, 2, 1));
        //    System.out.println(new ex13().compare(12, 101, 5));
    }

    // 深度优先遍历 DFS
    public int movingCount(int m, int n, int k) {
        if (k == 0) return 1;
        num = 0;
        isVisited = new boolean[m][n];
        dfs(m, n, 0, 0, k);
        return num;
    }

    private void dfs(int m, int n, int i, int j, int k) {
        if (i > m - 1 || j > n - 1 || isVisited[i][j] || !compare(i, j, k)) return;
        num++;
        isVisited[i][j] = true;
        dfs(m, n, i, j + 1, k); // 右
        dfs(m, n, i + 1, j, k); // 下
    }

    private boolean compare(int i, int j, int k) {
        int t = i;
        int sum = 0;
        while (t != 0) {
            sum += t % 10;
            t = t / 10;
        }
        t = j;
        while (t != 0) {
            sum += t % 10;
            t = t / 10;
        }
        return sum <= k;
    }

    // 广度优先遍历 BFS
    public int movingCount1(int m, int n, int k) {
        if (k == 0) return 1;
        num = 0;
        isVisited = new boolean[m][n];
        Queue<int[]> queue = new LinkedList<>(); // 辅助队列，用于存储临时结点
        queue.add(new int[] {0, 0});
        int[] x;
        int i, j;
        while (!queue.isEmpty()) {
            x = queue.poll();
            i = x[0];
            j = x[1];
            if (i < 0 || i > m - 1 || j < 0 || j > n - 1 || isVisited[i][j] || !compare(i, j, k))
                continue;
            isVisited[i][j] = true;
            num++;
            queue.add(new int[] {i, j + 1}); // 存入右边的格子
            queue.add(new int[] {i + 1, j}); // 存入下面的格子
        }
        return num;
    }
}
